// 为了解决未能找到类型或命名空间名“ILogger<>”的问题，需要添加对应的using指令
using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;
using System.Net.WebSockets;
using System.Text;
// 同时添加对 IOptions 的 using 指令

namespace Model.Core.Services
{
    public class WebSocketHelper : IAsyncDisposable
    {
        private IWebSocketClient _webSocketClient;
        private readonly ILogger<WebSocketHelper> _logger;
        // private readonly WebSocketOptions _options;

        #region 属性
        public bool _isConnect { get; set; }
        #endregion


        private string _uri;

        #region 定时器
        Timer GetConnectingTimer { get; set; }
        #endregion

        public bool isConnect()
        {
            if (_webSocketClient == null) return false;
            if (_webSocketClient.State == WebSocketState.Open)
            {
                return true;
            }
            return false;

        }
        #region 回调
        public Action<bool> ConnectedStatusAction { get; set; }
        public Action<bool> OnConnectedAction { get; set; }
        /// <summary>
        /// 用于信息回传
        /// </summary>
        public Action<string> RecvDataAction { get; set; }


        public Action<string> ErrorMsgCallBackAction { get; set; }
        #endregion
        public WebSocketHelper(IWebSocketClient webSocketClient, ILogger<WebSocketHelper> logger)
        {
            _webSocketClient = webSocketClient;
            _logger = logger;
            //   _options = options.Value;

            // 初始化心跳参数
            _heartbeatInterval = TimeSpan.FromSeconds(30);
            _heartbeatTimeout = TimeSpan.FromSeconds(45);

            _ = ReceiveLoopAsync();
            _ = SendLoopAsync();
            _ = HeartbeatLoopAsync();
        }

        private async Task ReceiveLoopAsync()
        {
            var buffer = new byte[1024 * 5];
            try
            {
                while (!_cts.IsCancellationRequested)
                {
                    if (_webSocketClient.State == WebSocketState.Open)
                    {
                        var result = await _webSocketClient.ReceiveAsync(
                            new ArraySegment<byte>(buffer),
                            _cts.Token);

                        // 更新心跳时间戳
                        if (result.MessageType == WebSocketMessageType.Text)
                        {
                            _lastPongReceived = DateTime.UtcNow;
                            // continue;
                        }

                        _logger.LogDebug("收到 {ByteCount} 字节数据", result.Count);

                        var lastbyte = ByteCut(buffer, 0x00);
                        var recvData = Encoding.UTF8.GetString(lastbyte, 0, lastbyte.Length);

                        // 处理完数据后重置缓冲区
                        Array.Clear(buffer, 0, buffer.Length);
                        _logger.LogDebug("收到 字节数据:{recvData}", recvData);
                        RecvDataAction?.Invoke(recvData);
                    }
                    await Task.Delay(20, _cts.Token);
                }
            }
            catch (OperationCanceledException)
            {
                _logger.LogInformation("接收循环已正常终止");
            }
            catch (WebSocketException ex) when (ex.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely)
            {
                _logger.LogWarning(ex, "WebSocket连接异常中断");
                ErrorMsgCallBackAction?.Invoke("连接已中断，正在尝试重连...");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "接收循环异常 (状态: {WebSocketState})", _webSocketClient.State);
                ErrorMsgCallBackAction?.Invoke($"接收错误: {ex.Message}");
            }
        }

        public async Task ConnectAsync(string uri)
        {
            _uri = uri;
            try
            {
                using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)))
                {
                    await _webSocketClient.ConnectAsync(new Uri(uri), cts.Token);
                }
                OnConnectedAction?.Invoke(_webSocketClient.State == WebSocketState.Open);
                _logger.LogInformation("成功连接到WebSocket服务器 {Uri}", uri);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "WebSocket连接失败 {Uri}", uri);
                OnConnectedAction?.Invoke(false);
                //_ = ReconnectAsync();
            }
        }

        /// <summary>
        /// 用于断线重连
        /// </summary>
        /// <param name="s"></param>
        //private async void GetConnectingTimerFunc(object s)
        //{
        //    bool status = isConnect();
        //    if (!status)
        //    {
        //        try
        //        {
        //            var oldSocket = _webSocketClient;
        //            // 由于 _webSocketClient 是只读字段，不能直接重新赋值，这里使用接口类型的新实例替换
        //            // 假设存在一个工厂方法来创建 IWebSocketClient 实例
        //            _webSocketClient = WebSocketClientFactory.CreateWebSocketClient();

        //            // 释放旧连接
        //            if (oldSocket != null && oldSocket.State == WebSocketState.Open)
        //            {
        //                await oldSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Reconnecting", _cts.Token);
        //                oldSocket.Dispose();
        //            }

        //            // 异步连接并添加指数退避
        //            const int _maxReconnectAttempts = 5;
        //            const double _baseDelaySeconds = 1.5;
        //            var retryDelay = TimeSpan.FromSeconds(Math.Min(_baseDelaySeconds * Math.Pow(2, _reconnectAttempts), 30));
        //            _logger.LogInformation("尝试第 {Attempts} 次重连，等待 {Delay} 秒...", _reconnectAttempts + 1, retryDelay.TotalSeconds);

        //            await Task.Delay(retryDelay, _cts.Token);
        //            await _webSocketClient.ConnectAsync(new Uri(_uri), _cts.Token);
        //            _reconnectAttempts = _webSocketClient.State == WebSocketState.Open ? 0 : Math.Min(_reconnectAttempts + 1, _maxReconnectAttempts);
        //            OnConnectedAction?.Invoke(isConnect());
        //        }
        //        catch (Exception ex)
        //        {
        //            _logger.LogError(ex, "WebSocket连接失败，已尝试 {Attempts} 次. 错误信息: {Message}", _reconnectAttempts, ex.Message);
        //            OnConnectedAction?.Invoke(false);
        //        }
        //    }
        //    ConnectedStatusAction?.Invoke(status);
        //}

        public void SendMsg(string msg)
        {
            SendconcurrentQueueDatas.Enqueue(msg);
        }
        ConcurrentQueue<string> SendconcurrentQueueDatas { get; set; } = new ConcurrentQueue<string>();
        private async Task SendLoopAsync()
        {
            try
            {
                while (!_cts.IsCancellationRequested)
                {
                    if (SendconcurrentQueueDatas.TryDequeue(out string sendmsg)
                        && _webSocketClient.State == WebSocketState.Open)
                    {
                        var buffer = Encoding.UTF8.GetBytes(sendmsg);
                        await _webSocketClient.SendAsync(
                            new ArraySegment<byte>(buffer),
                            WebSocketMessageType.Text,
                            true,
                            _cts.Token);

                        _logger.LogDebug("成功发送 {ByteCount} 字节数据", buffer.Length);
                    }
                    await Task.Delay(20, _cts.Token);
                }
            }
            catch (OperationCanceledException)
            {
                _logger.LogInformation("发送循环已正常终止");
            }
            catch (WebSocketException ex) when (ex.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely)
            {
                _logger.LogWarning(ex, "发送时连接异常中断");
                ErrorMsgCallBackAction?.Invoke("连接中断，发送失败");
                _ = ReconnectAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发送循环异常 (状态: {WebSocketState})", _webSocketClient.State);
                ErrorMsgCallBackAction?.Invoke($"发送错误: {ex.Message}");
            }
        }

        private static byte[] ByteCut(byte[] buf, int cut)
        {
            var list = new List<byte>();
            list.AddRange(buf);
            for (var i = list.Count - 1; i >= 0; i--)
            {
                if (list[i] == cut)
                {
                    list.RemoveAt(i);
                }
                else
                {
                    break;
                }
            }
            var lastbyte = new byte[list.Count];
            for (var i = 0; i < list.Count; i++)
            {
                lastbyte[i] = list[i];
            }
            return lastbyte;
        }

        private CancellationTokenSource _cts = new CancellationTokenSource();
        private int _reconnectAttempts = 0;
        private DateTime _lastPongReceived = DateTime.UtcNow;
        private readonly TimeSpan _heartbeatInterval;
        private readonly TimeSpan _heartbeatTimeout;

        private async Task HeartbeatLoopAsync()
        {
            try
            {
                while (!_cts.IsCancellationRequested)
                {
                    await Task.Delay(_heartbeatInterval, _cts.Token);

                    if (_webSocketClient.State == WebSocketState.Open &&
                        DateTime.UtcNow - _lastPongReceived > _heartbeatTimeout)
                    {
                        _logger.LogWarning("心跳超时，触发重连");
                        await ReconnectAsync();
                        continue;
                    }

                    var pingBuffer = Encoding.UTF8.GetBytes("\u200B");
                    await _webSocketClient.SendAsync(
                        new ArraySegment<byte>(pingBuffer),
                        WebSocketMessageType.Text,
                        true,
                        _cts.Token);
                }
            }
            catch (OperationCanceledException)
            {
                _logger.LogInformation("心跳循环已终止");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "心跳循环异常，触发重连机制");
                await ReconnectAsync();
            }
        }

        private async Task ReconnectAsync()
        {
            const int maxRetryCount = 1000;
            while (!_cts.IsCancellationRequested && _reconnectAttempts < maxRetryCount)
            {
                try
                {
                    // 重置心跳相关状态
                    _lastPongReceived = DateTime.UtcNow;

                    if (_webSocketClient != null)
                    {
                        await _webSocketClient.DisposeAsync();
                        // 由于 WebSocketClientFactory 未定义，使用现有的 WebSocketClient 类来创建实例
                        _webSocketClient = new WebSocketClient();
                    }

                    await ConnectAsync(_uri);

                    if (_webSocketClient.State == WebSocketState.Open)
                    {
                        _reconnectAttempts = 0;
                        return;
                    }

                    var delay = TimeSpan.FromSeconds(Math.Min(Math.Pow(2, _reconnectAttempts), 30));
                    _logger.LogInformation($"第{_reconnectAttempts + 1}次重连尝试，{delay.TotalSeconds}秒后重试 (最大尝试次数:{maxRetryCount})");
                    await Task.Delay(delay, _cts.Token);
                    _reconnectAttempts++;
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "重连过程中发生异常");
                    await Task.Delay(TimeSpan.FromSeconds(20), _cts.Token);
                }
            }
        }


        public async ValueTask DisposeAsync()
        {
            _cts.Cancel();
            try
            {
                GetConnectingTimer?.Dispose();
                if (_webSocketClient != null)
                {
                    await _webSocketClient.DisposeAsync();
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "资源释放异常");
            }
            finally
            {
                _cts.Dispose();
            }
        }
    }



    public interface IWebSocketClient : IAsyncDisposable
    {
        WebSocketState State { get; }
        Task ConnectAsync(Uri uri, CancellationToken cancellationToken);
        Task<WebSocketReceiveResult> ReceiveAsync(ArraySegment<byte> buffer, CancellationToken cancellationToken);
        Task SendAsync(ArraySegment<byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken);
    }

    public class WebSocketClient : IWebSocketClient
    {
        private readonly ClientWebSocket _socket = new();

        public WebSocketState State => _socket.State;

        public async Task ConnectAsync(Uri uri, CancellationToken cancellationToken)
        {
            await _socket.ConnectAsync(uri, cancellationToken);
        }

        public async Task<WebSocketReceiveResult> ReceiveAsync(ArraySegment<byte> buffer, CancellationToken cancellationToken)
        {
            return await _socket.ReceiveAsync(buffer, cancellationToken);
        }

        public async Task SendAsync(ArraySegment<byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken)
        {
            await _socket.SendAsync(buffer, messageType, endOfMessage, cancellationToken);
        }

        public async ValueTask DisposeAsync()
        {
            if (_socket.State == WebSocketState.Open)
            {
                await _socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
            }
            _socket.Dispose();
            GC.SuppressFinalize(this);
        }
    }


}
